package com.lagou;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ApplicationContext {


        private static final String SINGLETON = "singleton";
        private static final String PROTOTYPE = "prototype";

        private Class configClass;

        /**
         * 单例bean池
         */
        private Map<String, Object> singleTonBeanMap = new ConcurrentHashMap<>();

        /**
         * bena定义map
         */
        private Map<String, Object> beanDefinitionMap = new ConcurrentHashMap<>();


        public ApplicationContext(Class configClass) {
            this.configClass = configClass;

            /**
             * 扫描类，初始化 beanDefinitio
             */
            scan(configClass);

            /**
             * 创建bean
             */
            createBean(beanDefinitionMap);


        }

        private void createBean(Map<String, Object> beanDefinitionMap) {
            for (Map.Entry<String, Object> beanDefinitionEntry : beanDefinitionMap.entrySet()) {
                String beanName = beanDefinitionEntry.getKey();
                Object beanDefinition = beanDefinitionEntry.getValue();

                Class clazz = beanDefinition.getClass();
                try {
                    Object o = clazz.getDeclaredConstructor().newInstance();
                    singleTonBeanMap.put(beanName, o);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
            }
        }

        private void scan(Class configClass) {
            //解析配置类
            //ComponentScan注解-->扫描路径-->扫描
            ComponentScan componentScanAnnotation = (ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
            String path = componentScanAnnotation.value();
            System.out.println(path);
             path = path.replace(".", "/");
            ClassLoader classLoader = ApplicationContext.class.getClassLoader();
            URL resource = classLoader.getResource(path);
            File file = new File(resource.getFile());
            if (file.isDirectory()) {
                File[] files = file.listFiles();

                for (File f : files) {
                    String fileName = f.getAbsolutePath();
                    System.out.println(fileName);
                    if (fileName.endsWith(".class")) {

                        try {
                            String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
                            className = className.replace("\\", ".");
                            System.out.println(className);

                            Class<?> clazz = classLoader.loadClass(className);
                            if (clazz.isAnnotationPresent(Bean.class)) {

                                Bean componentAnnotation = clazz.getDeclaredAnnotation(Bean.class);
                                String beanName = componentAnnotation.value();
                                Object o = clazz.getDeclaredConstructor().newInstance();
                                beanDefinitionMap.put(beanName, o);
                                System.out.println(beanName);
                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }


                }
            }
        }

        public Object getBean(String beanName) {
            Object beanDefinition = beanDefinitionMap.get(beanName);

            if (beanDefinition == null) {
                //随便抛错
                throw new NullPointerException();
            }

            Object result = null;

                result = singleTonBeanMap.get(beanName);

            return result;
        }
    }

